﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.Xml.Serialization;
using Microsoft.Office.Interop.Excel;

namespace ObjectModel.Excel.Old
{
    /// <summary>
    /// Encapsulates a serializable range object using a series of lookup steps.
    /// </summary>
    public class LookUpStepRange : ConditionalOfflineRange
    {
        private int mGlobalRowOffset;
        private int mGlobalColOffset;
        
        public ObservableCollection<LookUpStep> ColLookUpSteps { get; set; }
        public ObservableCollection<LookUpStep> RowLookUpSteps { get; set; }

    	public DynamicLookupDimension Height { get; set; }
    	public DynamicLookupDimension Width { get; set; }

		public LookUpStepRange() {

			Height = new DynamicLookupDimension(value:1, direction:Dimension.Height);
			Width = new DynamicLookupDimension(value:1, direction:Dimension.Width);

			Height.PropertyChanged += HeightChanged;
			Width.PropertyChanged += WidthChanged;

			ColLookUpSteps = new ObservableCollection<LookUpStep>();
			RowLookUpSteps = new ObservableCollection<LookUpStep>();

			ColLookUpSteps.CollectionChanged += LookUpStepsOnCollectionChanged;
			RowLookUpSteps.CollectionChanged += LookUpStepsOnCollectionChanged;
		}

    	void LookUpStepsOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
    		if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
                foreach (LookUpStep step in e.NewItems)
                    step.PropertyChanged += (o, ea) => { OnPropertyChanged("LookUpSteps"); };
			
            OnPropertyChanged("LookUpSteps");
    	}

		void HeightChanged(object sender, PropertyChangedEventArgs e) {
    		
            OnPropertyChanged(string.Format("Height:{0}", e.PropertyName));
    	}

		void WidthChanged(object sender, PropertyChangedEventArgs e) {
    		
            OnPropertyChanged(string.Format("Width:{0}", e.PropertyName));
    	}
        
        public int GlobalRowOffset
        {
            get { return mGlobalRowOffset; }
            set
            {
                mGlobalRowOffset = value;
                OnPropertyChanged("GlobalRowOffset");
            }
        }
        
        public int GlobalColOffset
        {
            get { return mGlobalColOffset; }
            set
            {
                mGlobalColOffset = value;
                OnPropertyChanged("GlobalColOffset");
            }
        }

        [XmlIgnore]
        public override Range Range
        {
            get
            {                
                Range resolvedRange = null;
                Range colRange = Worksheet.Cells[1, 1];
                Range rowRange = Worksheet.Cells[1, 1];

                foreach (LookUpStep step in RowLookUpSteps)
                    rowRange = step.Resolve(rowRange);

                foreach (LookUpStep step in ColLookUpSteps)
                    colRange = step.Resolve(colRange);
                
                if (colRange != null && rowRange != null)
                    resolvedRange = Worksheet.Range[Worksheet.Cells[rowRange.Row + GlobalRowOffset, colRange.Column + GlobalColOffset],
                        Worksheet.Cells[rowRange.Row + GlobalRowOffset + Height.Resolve(Worksheet.Cells[rowRange.Row, colRange.Column]) - 1, 
						colRange.Column + GlobalColOffset + Width.Resolve(Worksheet.Cells[rowRange.Row, colRange.Column]) -1]];
                else
                    throw new InvalidOperationException("Could not resolve range from lookup steps.");

                return resolvedRange;
            }
        }
    }
}
